package org.systm.menu.service;

import org.global.basic.BaseServiceOpImpl;
import org.global.basic.CurdFindRepository;
import org.global.utils.ProBeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.systm.adminuser.entity.UserPermission;
import org.systm.adminuser.entity.UserRole;
import org.systm.adminuser.service.UserPermissionService;
import org.systm.adminuser.service.UserRoleService;
import org.systm.adminuser.service.condition.UserPermissionQuery;
import org.systm.adminuser.service.condition.UserRoleQuery;
import org.systm.menu.dao.MenuStore;
import org.systm.menu.entity.Menu;
import org.systm.menu.entity.MenuType;
import org.systm.menu.entity.PageMeta;
import org.systm.menu.params.MenuServiceParams;
import org.systm.menu.params.PageMetaServiceParams;
import javax.annotation.Resource;
import javax.persistence.EntityManager;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class MenuService extends BaseServiceOpImpl<Menu, String, MenuServiceParams<String>> {
    @Resource
    MenuStore menuStore;

    @Resource
    PageMetaService pageMetaService;

    @Resource
    EntityManager entityManager;

    @Resource
    UserPermissionService permissionService;

    @Override
    public CurdFindRepository<Menu, String> repository() {
        return menuStore;
    }

    @Override
    @Transactional
    public Menu save(MenuServiceParams<String> params) {
        Menu menu = params.get();
        if (params.getMeta() != null && menu.getMenuType() != MenuType.PERM) {
            PageMetaServiceParams<String> pageMetaServiceParams = new PageMetaServiceParams<>();
            pageMetaServiceParams.set(params.getMeta());
            PageMeta pageMeta = pageMetaService.save(pageMetaServiceParams);
            menu.setMeta(pageMeta);
            super.save(params);
            params.set(menu);
            return menu;
        } else if (menu.getMenuType() == MenuType.PERM){
            menu.setComponent("#");
            menu.setPath("#");
            // 权限标识
            String name = menu.getName();
            boolean flag = name != null;
            if (flag) {
                Optional<UserPermission> perOp = permissionService.findOne(UserPermissionQuery.perSpec.apply(name));
                if (perOp.isPresent()) {
                    UserPermission userPermission = perOp.get();
                    PageMeta pageMeta = new PageMeta();
                    pageMeta.setTitle(userPermission.getSpec());
                    pageMetaService.repository().save(pageMeta);
                    menu.setMeta(pageMeta);
                }
            }
            if (!flag) throw new RuntimeException("权限标识不存在");
            return super.save(params);
        }
        throw new RuntimeException("新增菜单失败");
    }

    @Override
    @Transactional
    public Menu update(MenuServiceParams<String> menuServiceParams) throws IllegalAccessException {
        PageMetaServiceParams<String> meta = new PageMetaServiceParams<>();
        meta.setMeta(menuServiceParams.getMeta());
        meta.setId(menuServiceParams.getMeta().getId());
        pageMetaService.update(meta);
        return super.update(menuServiceParams);
    }

    @Override
    public Menu del(MenuServiceParams<String> menuParams) {
        if (menuParams.getId() == null) throw new RuntimeException("清选择父级菜单");
        // 查询一个节点的所有叶子节点
        String cid = menuStore.cid(menuParams.getId());
        List<String> menuIds = new ArrayList<>();
        if (cid != null) {
            menuIds .addAll( Arrays.stream(cid.split(",")).collect(Collectors.toList()));
        }
        menuIds.add(menuParams.getId());
        // 1.删除所有叶子节点
        List<Menu> menus = super.delByIds(menuIds);
        // 维护角色的权限
        List<List<String>> menuRoles = menus.stream()
                .map(e -> e.getMeta().getRoles())
                .collect(Collectors.toList());
        Set<String> setRole = new HashSet<>();
        for (List<String> roles : menuRoles) setRole.addAll(roles);
        UserRoleService roleService = ProBeanUtils.getBean(UserRoleService.class);
        Optional<List<UserRole>> allRole = roleService.findAll(UserRoleQuery.byRoleNames.apply(setRole));
        if (allRole.isPresent()) {
            // 要被删除的权限
            List<String> perIds = menus.stream()
                    .filter((menu -> menu.getMenuType() == MenuType.PERM))
                    .map(menu -> menu.getMenuType().getType())
                    .collect(Collectors.toList());

            List<UserRole> userRoles = allRole.get();
            for (UserRole userRole : userRoles) {
                // 2. 维护角色的菜单列表，菜单被删，角色列表的菜单也要维护
                List<String> roleMenuId = userRole.getMenuIds().stream()
                        .filter((menuId -> menuIds.stream().noneMatch((exMenuId) -> Objects.equals(menuId, exMenuId))))
                        .collect(Collectors.toList());
                userRole.setMenuIds(roleMenuId);

                // 3. 维护角色的权限列表
                List<UserPermission> rolePermission = userRole.getPermissions().stream()
                        .filter((per) -> perIds.stream().noneMatch((perId -> Objects.equals(perId, per.getId()))))
                        .collect(Collectors.toList());
                userRole.setPermissions(rolePermission);
            }
            roleService.repository().saveAll(userRoles);
        }
        return null;
    }

    @Override
    public EntityManager entityManger() {
        return this.entityManager;
    }
}
